import { useTagsStore } from '@/store/modules/tags'
import { CloseOutlined, LeftOutlined, ReloadOutlined, RightOutlined } from '@vicons/antd'
import { NIcon } from 'naive-ui'
import { defineComponent, PropType, ref, toRefs, watch } from 'vue'
import TagBackgroundSVG from './TagBackgroundSVG.vue'
import { RouteLocationNormalized, useRoute, useRouter } from 'vue-router'
import styles from './index.module.scss'
import { useElementSize, useTransition } from '@vueuse/core'
import { useAppStore } from '@/store/modules/app'

const TagItem = defineComponent({
  name: 'TagItem',
  props: {
    tag: {
      type: Object as PropType<RouteLocationNormalized>,
      required: true,
    },
    active: {
      type: Boolean as PropType<boolean>,
      required: true,
    },
  },
  setup: (props, { emit }) => {
    const tagStore = useTagsStore()
    const { tag, active } = toRefs(props)
    const domRef = ref<HTMLElement | null>(null)
    const router = useRouter()
    const tagBgColor = ref<[string, string]>(['#ffffff', '#18181c'])
    const tagHoverColor = ref<[string, string]>(['#dee1e6', '#333333'])
    const mixColor = ref<[string, string]>(['#ffffff', '#000000'])
    const appStore = useAppStore()

    watch(
      () => appStore.theme,
      theme => {
        if (theme.name === 'dark') {
          tagBgColor.value = ['#18181c', '#ffffff']
          tagHoverColor.value = ['#333333', '#dee1e6']
          mixColor.value = ['#000000', '#ffffff']
        } else {
          tagBgColor.value = ['#ffffff', '#18181c']
          tagHoverColor.value = ['#dee1e6', '#333333']
          mixColor.value = ['#ffffff', '#000000']
        }
      },
      {
        immediate: true,
      }
    )

    function ItemClick() {
      router.push({ path: tag.value.path })
    }
    watch(
      () => router.currentRoute.value.path,
      path => {
        if (path === tag.value.path) {
          const dom = domRef.value
          const domOffset = (dom?.offsetLeft || 0) + (dom?.offsetWidth || 0)
          const wrapWidth = dom?.parentElement?.parentElement?.offsetWidth || 0
          const bodyLeft = dom?.parentElement?.offsetLeft || 0
          const page = Math.floor(Math.abs(bodyLeft) / wrapWidth)
          const goLeft = (dom?.offsetLeft || 0) - (dom?.offsetWidth || 0)
          const tagIsPage = Math.floor(domOffset / wrapWidth)

          if (tagIsPage !== page) {
            emit('scrollTo', goLeft)
          }
        }
      }
    )

    return () => (
      <div
        onClick={ItemClick}
        class={[styles.tag_item, active.value && styles.tag_item_active]}
        ref={domRef}
      >
        <span class={styles.tag_title}>{tag.value.meta.title}</span>
        <TagBackgroundSVG
          class={styles.tag_bg}
          isActive={props.active}
          hoverBgColor={tagHoverColor.value}
          bgColor={tagBgColor.value}
          mixColor={mixColor.value}
        />
        <span class={styles.tag_icons}>
          <span onClick={() => tagStore.removeTag(tag.value)}>
            <NIcon class={[styles.tag_icon]} style={{ display: !active.value ? 'none' : '' }}>
              <ReloadOutlined />
            </NIcon>
          </span>
          <span onClick={() => tagStore.removeTag(tag.value)}>
            <NIcon class={styles.tag_icon}>
              <CloseOutlined />
            </NIcon>
          </span>
        </span>
      </div>
    )
  },
})

const Tags = defineComponent(() => {
  const tagStore = useTagsStore()
  const route = useRoute()
  const wrapRef = ref<HTMLElement | null>(null)
  const bodyRef = ref<HTMLElement | null>(null)
  const { width: bodyWidth } = useElementSize(bodyRef)
  const showPageControl = ref(false)
  const scrollNumber = ref(0)

  const cubicBezierNumber = useTransition(scrollNumber, {
    duration: 800,
    transition: [0.25, 0.6, 0.85, 1],
  })
  function activeRoute(tag: RouteLocationNormalized) {
    return tag.path === route.path
  }

  function nextPage() {
    const wrapWidth = wrapRef.value?.offsetWidth || 0
    const bodyWidth = bodyRef.value?.offsetWidth || 0
    // 当前所在页数计算
    const page = Math.floor(scrollNumber.value / wrapWidth)
    const maxPage = Math.ceil(wrapWidth / bodyWidth)
    if (page < maxPage) {
      scrollTo((page + 1) * wrapWidth)
    } else {
      scrollTo(0)
    }
  }

  function prePage() {
    const wrapWidth = wrapRef.value?.offsetWidth || 0
    // 当前所在页数计算
    const page = Math.floor(scrollNumber.value / wrapWidth)

    if (page === 0) {
      scrollTo(0)
    } else {
      scrollTo((page - 1) * wrapWidth)
    }
  }

  watch(
    () => bodyWidth.value,
    width => {
      showPageControl.value = width > (wrapRef.value?.offsetWidth || 0)
    }
  )

  watch(
    () => cubicBezierNumber.value,
    value => {
      const bodyDom = bodyRef.value
      if (bodyDom) {
        bodyDom.style.left = `-${value}px`
      }
    }
  )
  function scrollTo(x: number) {
    scrollNumber.value = x
  }

  return () => (
    <div class={styles.wrap}>
      <div
        class={styles.left_btn}
        onClick={prePage}
        style={{ display: showPageControl.value ? 'block' : 'none' }}
      >
        <NIcon size={18}>
          <LeftOutlined />
        </NIcon>
      </div>
      <div
        class={styles.right_btn}
        onClick={nextPage}
        style={{ display: showPageControl.value ? 'block' : 'none' }}
      >
        <NIcon size={18}>
          <RightOutlined />
        </NIcon>
      </div>
      <div ref={wrapRef} class={[styles.tags_wrap]}>
        <div ref={bodyRef} class={styles.tags_body}>
          {tagStore.tags.map(tag => (
            <TagItem tag={tag} onScrollTo={scrollTo} active={activeRoute(tag)} />
          ))}
        </div>
      </div>
    </div>
  )
})

export default Tags
